package cn.texous.easytalk.commonutil.util;

import org.springframework.beans.BeanUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 只是对象之间进行转换，采用的是浅拷贝的方式
 *
 * @author Showa.L
 * @since 2019/5/5 14:03
 */
public class ConverterUtils {

    /**
     * 对象之间转换
     *
     * @param clazz  转换类型
     * @param object 需要转换的对象
     * @param <T>    类型
     * @return
     */
    public static <T> T convert(Class<T> clazz, Object object) {
        T obj = null;
        if (object != null) {
            try {
                obj = clazz.newInstance();
                BeanUtils.copyProperties(object, obj);
            } catch (InstantiationException var4) {
                var4.printStackTrace();
            } catch (IllegalAccessException var5) {
                var5.printStackTrace();
            }
        }

        return obj;
    }

    /**
     * 数组对象转换
     *
     * @param clazz   目标类型
     * @param objList 源列表
     * @param <T>     目标类型
     * @param <D>     源类型
     * @return
     */
    public static <T, D> List<T> convert(Class<T> clazz, List<D> objList) {
        List<T> resultList = new ArrayList<>();
        if (objList != null && !objList.isEmpty()) {
            Iterator<D> var3 = objList.iterator();

            while (var3.hasNext()) {
                D obj = var3.next();
                resultList.add(convert(clazz, obj));
            }
        }
        return resultList;
    }

    /**
     * map to bean
     *
     * @param tClass 目标类型
     * @param map    源数据
     * @param <T>    目标类型
     * @param <D>    源类型
     * @return
     */
    public static <T, D> T transMap2Bean(Class<T> tClass, Map<String, D> map) {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(tClass);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            T t = tClass.newInstance();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                String key2 = StringUtils.underscoreName(key);
                if (map.containsKey(key)) {
                    D value = map.get(key);
                    // 得到property对应的setter方法
                    Method setter = property.getWriteMethod();
                    setter.invoke(t, value);
                } else if (map.containsKey(key2)) {
                    D value = map.get(key2);
                    // 得到property对应的setter方法
                    Method setter = property.getWriteMethod();
                    setter.invoke(t, value);
                }
            }
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * map 列表到 bean 列表
     *
     * @param tClass  目标类型
     * @param origins 源数据
     * @param <T>     目标类型
     * @param <D>     源数据类型
     * @return
     */
    public static <T, D> List<T> transMap2Bean(Class<T> tClass, List<Map<String, D>> origins) {
        if (origins == null || origins.isEmpty())
            return null;
        List<T> list = new ArrayList<>();
        for (Map<String, D> origin : origins) {
            list.add(transMap2Bean(tClass, origin));
        }
        return list;
    }

    /**
     * bean 转 map
     *
     * @param obj 源对象
     * @param <T> 源类型
     * @return
     */
    public static <T> Map<String, Object> transBean2Map(T obj) {
        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, value);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 目标数组转 map 数组
     *
     * @param objs 源数据
     * @param <T>  源类型
     * @return
     */
    public static <T> List<Map<String, Object>> transBean2Map(List<T> objs) {
        if (objs == null || objs.isEmpty())
            return null;

        List<Map<String, Object>> resultList = new ArrayList<>();
        for (T t : objs) {
            resultList.add(transBean2Map(t));
        }
        return resultList;
    }

    /**
     * 目标转 string map
     *
     * @param obj 源数据
     * @param <T> 源类型
     * @return
     */
    public static <T> Map<String, String> transBean2StringMap(T obj) {
        if (obj == null) {
            return null;
        }
        Map<String, String> map = new HashMap<>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    if (value == null) {
                        map.put(key, null);
                        continue;
                    }
                    if (value instanceof String)
                        map.put(key, (String) value);
                    else
                        map.put(key, String.valueOf(value));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 将列表对象转为 key map 列表
     *
     * @param originList 源列表
     * @param <T> 源类型
     * @return
     */
    public static <T> List<Map<String, T>> transList2MapList(List<T> originList) {
        List<Map<String, T>> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(originList)) {
            for (T str : originList) {
                Map<String, T> item = new HashMap<>();
                item.put("key", str);
                result.add(item);
            }
        }
        return result;
    }

}
